package com.ctshk.rpc.goods.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.GlobalConstants;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.rpc.goods.dto.AttributeList;
import com.ctshk.rpc.goods.dto.CommoditySpecificationsNameDTO;
import com.ctshk.rpc.goods.dto.CommoditySpecificationsPageDTO;
import com.ctshk.rpc.goods.dto.SpecificationsList;
import com.ctshk.rpc.goods.entity.CommoditySpecifications;
import com.ctshk.rpc.goods.entity.CommoditySpecificationsAttribute;
import com.ctshk.rpc.goods.entity.CommoditySpecificationsName;
import com.ctshk.rpc.goods.mapper.CommoditySpecificationsAttributeMapper;
import com.ctshk.rpc.goods.mapper.CommoditySpecificationsMapper;
import com.ctshk.rpc.goods.mapper.CommoditySpecificationsNameMapper;
import com.ctshk.rpc.goods.req.CommoditySpecificationsAddReq;
import com.ctshk.rpc.goods.req.CommoditySpecificationsAttributeAddReq;
import com.ctshk.rpc.goods.req.CommoditySpecificationsNameAddReq;
import com.ctshk.rpc.goods.req.CommoditySpecificationsNamePageReq;
import com.ctshk.rpc.goods.service.ICommoditySpecificationsNameService;
import com.ctshk.rpc.system.service.ISysPermissionService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * <p>
 * 商品规格名称 服务实现类
 * </p>
 *
 * @author 姜斌文
 * @since 2021-04-12
 */
@DubboService
public class CommoditySpecificationsNameServiceImpl extends ServiceImpl<CommoditySpecificationsNameMapper, CommoditySpecificationsName> implements ICommoditySpecificationsNameService {
	
	@Autowired
	private CommoditySpecificationsNameMapper nameMapper;
	@Autowired
	private CommoditySpecificationsMapper specificationsMapper;
	@Autowired
	private CommoditySpecificationsAttributeMapper attributeMapper;
	@DubboReference
	private ISysPermissionService sysPermissionService;

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void addCommoditySpecificationsName(CommoditySpecificationsNameAddReq addReq, Long userId) throws Exception {
		List<CommoditySpecificationsNameDTO> dbCurrentData = nameMapper.findCommoditySpecificationsNameByAll();
		checkAddCommoditySpecifications(addReq, dbCurrentData);
		CommoditySpecificationsName formName = new CommoditySpecificationsName();
		BeanUtils.copyProperties(addReq, formName, EntityUtil.getNullPropertyNames(addReq));
		LocalDateTime now=LocalDateTime.now();
		formName.setCreateId(userId);
		formName.setGmtCreate(now);
		formName.setModifiedId(userId);
		formName.setGmtModified(now);
		formName.setIsDeleted(IsDeletedCode.NO.getCode());
		nameMapper.insert(formName);
		List<CommoditySpecificationsAddReq> specificationsAddReqs = addReq.getCommoditySpecificationsAddReqs();
		if (null != specificationsAddReqs) {
			specificationsAddReqs.stream().forEach(specificationsObj -> {
	        	CommoditySpecifications specifications = new CommoditySpecifications();
	            BeanUtils.copyProperties(specificationsObj, specifications, EntityUtil.getNullPropertyNames(specificationsObj));
	            specifications.setSpecificationsNameId(formName.getId());
	    		specifications.setCreateId(userId);
	    		specifications.setGmtCreate(now);
	    		specifications.setModifiedId(userId);
	    		specifications.setGmtModified(now);
	    		specifications.setIsDeleted(IsDeletedCode.NO.getCode());
	    		specificationsMapper.insert(specifications);
	    		List<CommoditySpecificationsAttributeAddReq> attributes = specificationsObj.getCommoditySpecificationsAttributeAddReqs();
	    		if (null != attributes) {
	    			List<CommoditySpecificationsAttribute> attributeList = new ArrayList<CommoditySpecificationsAttribute>();
	    			attributes.stream().forEach(attributeObj -> {
	    				CommoditySpecificationsAttribute attribute = new CommoditySpecificationsAttribute();
	    				BeanUtils.copyProperties(attributeObj, attribute, EntityUtil.getNullPropertyNames(attributeObj));
	    				attribute.setSpecificationsNameId(formName.getId());
	    				attribute.setSpecificationsId(specifications.getId());
	    				attribute.setCreateId(userId);
	    				attribute.setGmtCreate(now);
	    				attribute.setModifiedId(userId);
	    				attribute.setGmtModified(now);
	    				attribute.setIsDeleted(IsDeletedCode.NO.getCode());
	    				attributeList.add(attribute);
	    			});
	    			attributeMapper.insertBatchSomeColumn(attributeList);
	    		}
	        });
		}
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void updateCommoditySpecificationsName(CommoditySpecificationsNameAddReq addReq, Long userId) throws Exception {
		CommoditySpecificationsName specificationsName = nameMapper.selectById(addReq.getId());
		List<CommoditySpecificationsNameDTO> dbCurrentData = nameMapper.findCommoditySpecificationsNameByAll();
		checkAddCommoditySpecifications(addReq, dbCurrentData);
        BeanUtils.copyProperties(addReq, specificationsName, EntityUtil.getNullPropertyNames(addReq));
		LocalDateTime now=LocalDateTime.now();
		specificationsName.setModifiedId(userId);
		specificationsName.setGmtModified(now);
		nameMapper.updateById(specificationsName);
		specificationsMapper.deleteBySpecificationsNameId(specificationsName.getId());
		List<CommoditySpecificationsAddReq> specificationss = addReq.getCommoditySpecificationsAddReqs();
		List<CommoditySpecificationsAttribute> specificationsAttrList = new ArrayList<CommoditySpecificationsAttribute>();
		for (CommoditySpecificationsAddReq specificationsObj : specificationss) {
			CommoditySpecifications specifications = new CommoditySpecifications();
	        BeanUtils.copyProperties(specificationsObj, specifications, EntityUtil.getNullPropertyNames(specificationsObj));
	        specifications.setSpecificationsNameId(specificationsName.getId());
			specifications.setCreateId(specificationsName.getCreateId());
			specifications.setGmtCreate(specificationsName.getGmtCreate());
			specifications.setIsDeleted(specificationsName.getIsDeleted());
			specifications.setModifiedId(userId);
			specifications.setGmtModified(now);
			specificationsMapper.insert(specifications);
    		attributeMapper.deleteByNameIdAndAttrId(specificationsName.getId(), specifications.getId());
			List<CommoditySpecificationsAttributeAddReq> specificationsAttributes  = specificationsObj.getCommoditySpecificationsAttributeAddReqs();
			specificationsAttributes.stream().forEach(specificationsAttributeObj ->{
				CommoditySpecificationsAttribute attributes = new CommoditySpecificationsAttribute();
		        BeanUtils.copyProperties(specificationsAttributeObj, attributes, EntityUtil.getNullPropertyNames(specificationsAttributeObj));
		        attributes.setSpecificationsId(specifications.getId());
		        attributes.setSpecificationsNameId(specifications.getSpecificationsNameId());
		        attributes.setCreateId(specifications.getCreateId());
		        attributes.setGmtCreate(specifications.getGmtCreate());
		        attributes.setIsDeleted(specifications.getIsDeleted());
		        attributes.setModifiedId(userId);
		        attributes.setGmtModified(now);
				specificationsAttrList.add(attributes);
				});

		}
		attributeMapper.insertBatchSomeColumn(specificationsAttrList);
	}

	@Override
	public PageResponse<CommoditySpecificationsPageDTO> findCommoditySpecificationsName(CommoditySpecificationsNamePageReq pageReq, TokenUser tokenUser) {

		Result<List<Long>> permissionResult = sysPermissionService.queryPermission(pageReq.getMenuId(), tokenUser.getId());
		if (!permissionResult.isSuccess()) {
			SystemError result = SystemError.getDefined(permissionResult.getCode());
			throw new BusinessException(result);
		}
		//不是管理员
		if (!GlobalConstants.Role.isAdmin(tokenUser.getUsername())) {
			pageReq.setIsNotAdmin(1);
			String ids = "";
			List<Long> data = permissionResult.getData();
			if(data != null && data.size() >0){
				for (Long datum : data) {
					ids += datum + ",";
				}
			}
			if(ids.length() > 0){
				ids = ids.substring(0, ids.length() - 1);
			}
			pageReq.setUserIds(ids);
		}

		IPage<CommoditySpecificationsPageDTO> page = new Page<CommoditySpecificationsPageDTO>(pageReq.getPageNo(),pageReq.getPageSize());
		// 分页查询商品规格名称
		IPage<CommoditySpecificationsPageDTO> iPage = nameMapper.findCommoditySpecificationsNameByPageAll(page, pageReq);
		List<CommoditySpecificationsPageDTO> recordsList = iPage.getRecords();
		List<CommoditySpecificationsPageDTO> pageDTOList = EntityUtil.copyList(recordsList, CommoditySpecificationsPageDTO.class);
		List<CommoditySpecificationsPageDTO> dbSonAll = nameMapper.findCommoditySpecificationsNameBySonAll();
		if (null != dbSonAll && dbSonAll.size() > 0) {
			Map<String, List<CommoditySpecificationsPageDTO>> result = dbSonAll.stream().collect(Collectors.groupingBy(obj -> obj.getSpecificationsNameId().toString()));
			for (CommoditySpecificationsPageDTO nameDTO : pageDTOList) {
				List<CommoditySpecifications> batchSpecificationsByNameId = specificationsMapper.findBatchSpecificationsByNameId(nameDTO.getId());
				if(batchSpecificationsByNameId != null && batchSpecificationsByNameId.size() > 0){
					List<SpecificationsList> specificationsLists = new ArrayList<>();
					for (CommoditySpecifications commoditySpecifications : batchSpecificationsByNameId) {
						SpecificationsList specificationsList = new SpecificationsList();
						specificationsList.setId(commoditySpecifications.getId());
						specificationsList.setSpecificationsName(commoditySpecifications.getSpecifications());
						List<CommoditySpecificationsAttribute> commoditySpecificationsAttributeList = attributeMapper.findCommoditySpecificationsAttributeListByNameIdAndSId(nameDTO.getId(), commoditySpecifications.getId());
						if(commoditySpecificationsAttributeList != null && commoditySpecificationsAttributeList.size() > 0){
							List<AttributeList> attributeLists = new ArrayList<>();
							for (CommoditySpecificationsAttribute commoditySpecificationsAttribute : commoditySpecificationsAttributeList) {
								AttributeList attributeList = new AttributeList();
								attributeList.setId(commoditySpecificationsAttribute.getId());
								attributeList.setAttributeName(commoditySpecificationsAttribute.getAttributeName());
								attributeLists.add(attributeList);
							}
							specificationsList.setAttributeLists(attributeLists);
						}
						specificationsLists.add(specificationsList);
					}
					nameDTO.setSpecificationsLists(specificationsLists);
				}


				if (result.containsKey(nameDTO.getId().toString())) {
					List<CommoditySpecificationsPageDTO> sonData = result.get(nameDTO.getId().toString());
					String specifications = "";
					String attributeName = "";
					for (CommoditySpecificationsPageDTO son : sonData) {
						specifications += son.getSpecifications()+",";
						attributeName += son.getAttributeName()+"\n";
					}
					if (specifications.length() > 0){
						specifications = specifications.substring(0,specifications.length() -1);
						nameDTO.setSpecifications(specifications);
					}
						nameDTO.setAttributeName(attributeName);
				}
			}
		}
		return new PageResponse<>(pageDTOList, iPage.getCurrent() == 1,
				iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()),
				iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
	}

	/**
	 * 入參校驗
	 * @param addReq 入參對象
	 * @param dbCurrentData 數據庫當前名稱集合
	 * @throws Exception 異常
	 */
	private void checkAddCommoditySpecifications(
			CommoditySpecificationsNameAddReq addReq,
			List<CommoditySpecificationsNameDTO> dbCurrentData) throws Exception {
		CommoditySpecificationsNameDTO commoditySpecificationsNameBySpecificationsName = nameMapper.findCommoditySpecificationsNameBySpecificationsName(addReq.getSpecificationsName());
		if(commoditySpecificationsNameBySpecificationsName != null && commoditySpecificationsNameBySpecificationsName.getSpecificationsName().equalsIgnoreCase(addReq.getSpecificationsName())){
			if(addReq.getId() != null && !addReq.getId().equals(commoditySpecificationsNameBySpecificationsName.getId())){
				throw new BusinessException(SystemError.MALL_MERCHANDISE_23008);
			}
			if(addReq.getId() == null){
				throw new BusinessException(SystemError.MALL_MERCHANDISE_23008);
			}
		}
		if (addReq.getSpecificationsName().length() > 100) {
			throw new BusinessException(SystemError.MALL_MERCHANDISE_23007);
		}
		List<CommoditySpecificationsAddReq> specificationsList = addReq.getCommoditySpecificationsAddReqs();
		if (null != specificationsList && specificationsList.size() > 2) {
			throw new BusinessException(SystemError.MALL_MERCHANDISE_23009);
		}
		if (null != specificationsList && specificationsList.size() > 0) {
			for (CommoditySpecificationsAddReq specification : specificationsList) {
				if (specification.getSpecifications().length() > 10) {
					throw new BusinessException(SystemError.MALL_MERCHANDISE_23010);
				}
				List<CommoditySpecificationsAttributeAddReq> specificationAttr = specification.getCommoditySpecificationsAttributeAddReqs();
				if (null != specificationAttr && specificationAttr.size() > 30) {
					throw new BusinessException(SystemError.MALL_MERCHANDISE_23011);
				}
				if(specificationAttr != null){
					for (CommoditySpecificationsAttributeAddReq attr : specificationAttr) {
						if (attr.getAttributeName().length() > 10) {
							throw new BusinessException(SystemError.MALL_MERCHANDISE_23010);
						}
					}
				}
			}
		}
	}
}
